#include "Group.h"
#include "Matrix4x4.h"

#include <cstdlib>

CGroup::CGroup(void)
: theInstance( NULL )
, NumChildren( 0 )
, theChildren( NULL )
, theTransform ( NULL )
{
}

CGroup::~CGroup(void)
{
	if (theTransform != NULL)
	{
		delete theTransform;
		theTransform = NULL;
	}
	if (theInstance != NULL)
	{
		delete theInstance;
		theInstance = NULL;
	}
}

void CGroup::Draw(void)
{
	if (theInstance)
	{
		glPushMatrix();
			if(theTransform)
				glMultMatrixf( (theTransform->GetTransform()).matrix );
			theInstance->Draw();
		glPopMatrix();
	}

	list<CNode*>::iterator i;
	for(i=theChildren.begin(); i != theChildren.end(); ++i) 
		(*i)->Draw();
}

void CGroup::SetInstance(CInstance* theInstance)
{
	this->theInstance = theInstance;
}

void CGroup::AddChild(CTransform* aNewTransform, CGroup* aNewGroup, CInstance* aNewInstance)
{
	aNewGroup->SetInstance( aNewInstance );
	aNewTransform->SetGroup( aNewGroup );
	theChildren.push_back( aNewTransform );
	NumChildren = theChildren.size();
}

void CGroup::SetTransform(CTransform *aNewTransform)
{
	theTransform = aNewTransform;
}

void CGroup::ApplyTranslate( const float dx, const float dy, const float dz )
{
	if (theTransform)
		theTransform->SetTranslate( dx, dy, dz );

	list<CNode*>::iterator i;
	for(i=theChildren.begin(); i != theChildren.end(); ++i) 
		((CTransform*)(*i))->SetTranslate( dx, dy, dz );
}

void CGroup::ApplyRotate(const float angle, const float dx, const float dy, const float dz)
{
	if (theTransform)
		theTransform->SetRotate( angle, dx, dy, dz );

	list<CNode*>::iterator i;
	for(i = theChildren.begin(); i != theChildren.end(); ++i)
		((CTransform*)(*i))->SetRotate( angle, dx, dy, dz );
}

void CGroup::ApplyScale(const float dx, const float dy, const float dz)
{
	if (theTransform)
		theTransform->SetScale( dx, dy, dz );

	list<CNode*>::iterator i;
	for(i=theChildren.begin(); i != theChildren.end(); ++i) 
		((CTransform*)(*i))->SetScale( dx, dy, dz );
}

//Get top left corner of the group
Vector3D CGroup::GetTopLeft(void)
{
	return Vector3D(theInstance->GetTopLeft().x + theTransform->GetTransform().matrix[theTransform->GetTransform().INDEX4(0,3)],
					theInstance->GetTopLeft().y + theTransform->GetTransform().matrix[theTransform->GetTransform().INDEX4(1,3)],
					theInstance->GetTopLeft().z + theTransform->GetTransform().matrix[theTransform->GetTransform().INDEX4(2,3)]);
}

//Get the bottom right corner of the group
Vector3D CGroup::GetBottomRight(void)
{
	return Vector3D(theInstance->GetBottomRight().x + theTransform->GetTransform().matrix[theTransform->GetTransform().INDEX4(0,3)],
					theInstance->GetBottomRight().y + theTransform->GetTransform().matrix[theTransform->GetTransform().INDEX4(1,3)],
					theInstance->GetBottomRight().z + theTransform->GetTransform().matrix[theTransform->GetTransform().INDEX4(2,3)]);
}

void CGroup::SetColor(const float red, const float green, const float blue)
{
	theInstance->SetColor(red, green, blue);
}